package com.arpa.wms.controller.wms;

import cn.hutool.core.collection.IterUtil;
import com.arpa.core.web.MediaTypes;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.Page;
import com.arpa.ntocc.common.common.constant.StrConsts;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.ShipmentWarehouseValidate;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.ntocc.common.security.annotation.NeedLogin;
import com.arpa.wms.domain.dto.ContractDTO;
import com.arpa.wms.domain.entity.Contract;
import com.arpa.wms.domain.vo.ContractVO;
import com.arpa.wms.service.IContractService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.*;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;


/**
 * <p>
 * 仓库计费合同 Controller
 * </p>
 *
 * @author LEO
 * @since 2020-11-17
 */
@Api(tags = "WMS仓库合同管理")
@RestController
@RequestMapping(value = "/contract", produces = "application/json;charset=UTF-8")
@Log4j2
@NeedLogin
public class ContractController {

    private final IContractService iContractService;

    public ContractController(IContractService iContractService) {
        this.iContractService = iContractService;
    }


    /**
     * 获取 仓库计费合同 列表
     *
     * @param contractDTO
     * @param request
     * @return
     */
    @ApiOperation(value = "获取仓库合同列表", notes = "获取仓库合同列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "gmtCreatedStart", value = "创建日期起", paramType = "query", dataType = "string", defaultValue = ""),
            @ApiImplicitParam(name = "gmtCreatedEnd", value = "创建日期止", paramType = "query", dataType = "string", defaultValue = ""),
            @ApiImplicitParam(name = "gmtModifiedStart", value = "修改日期起", paramType = "query", dataType = "string", defaultValue = ""),
            @ApiImplicitParam(name = "gmtModifiedEnd", value = "修改日期止", paramType = "query", dataType = "string", defaultValue = ""),
            @ApiImplicitParam(name = "createdName", value = "创建人", paramType = "query", dataType = "string", defaultValue = ""),
            @ApiImplicitParam(name = "modifiedName", value = "修改人", paramType = "query", dataType = "string", defaultValue = ""),
            @ApiImplicitParam(name = "pageNum", value = "第几页", paramType = "query", dataType = "int", defaultValue = "1"),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", paramType = "query", dataType = "int", defaultValue = "10"),
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = ContractVO.class))
    @GetMapping()
    public Result list(ContractDTO contractDTO, HttpServletRequest request) {
        try {
            //校验授权仓库code和货主code不能为空
            ShipmentWarehouseValidate.validateShipmentCodesAndWarehouseCodes();
            //登录账号授权的货主过滤
            contractDTO.setShipmentCodes(UserUtil.getAuthorizeShipmentCodes());
            //登录账号授权的仓库过滤
            contractDTO.setWarehouseCodes(UserUtil.getAuthorizeWarehouseCodes());
            //所属机构过滤
            contractDTO.setGroupCode(UserUtil.getBranchCode());
            ContractVO contractVO = iContractService.queryListSum(contractDTO);

            List<ContractVO> contractVOList = iContractService.queryList(contractDTO);
            Page returnPage = new Page(contractDTO.getPageNum(), contractDTO.getPageSize());
            returnPage.setRecords(contractVOList);
            returnPage.setTotal(contractVO.getTotal());
            returnPage.setSumObject(contractVO);
            return Result.ok().data(returnPage);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 添加 仓库计费合同
     *
     * @param entity  Contract
     * @param request
     * @return
     */
    @ApiOperation(value = "添加 仓库计费合同 ", notes = "添加 仓库计费合同 ")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
    })
    @PostMapping()
    public Result create(@RequestBody @Validated(Contract.Save.class)Contract entity, HttpServletRequest request) {
        try {
            iContractService.save(entity);
            return Result.ok("合同添加成功");
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 获取仓库计费合同详情
     *
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "获取仓库计费合同详情", notes = "获取仓库计费合同信息，包括作业费")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "code", value = "仓库计费合同code", paramType = "path", dataType = "String")
    })
    @ApiResponses(@ApiResponse(code = 0, message = "success", response = ContractVO.class))
    @GetMapping(value = "/{code}")
    public Result contract(@PathVariable String code, HttpServletRequest request) {
        try {
            ContractVO entity = iContractService.getContract(code);
            return Result.ok().data(entity);
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 修改仓库计费合同
     *
     * @param entity  仓库计费合同
     * @param request
     * @return
     */
    @ApiOperation(value = "修改仓库计费合同", notes = "修改仓库计费合同")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
    })
    @PutMapping()
    public Result update(@RequestBody @Validated(Contract.Update.class) Contract entity, HttpServletRequest request) {
        try {
            if (StringUtils.isBlank(entity.getCode())) {
                return Result.error("code不能为空");
            }
            iContractService.updateByCode(entity);
            return Result.ok("合同修改成功");
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }

    }

    /**
     * 删除 仓库计费合同
     *
     * @param code 合同标识
     * @param request
     * @return
     */
    @ApiOperation(value = "删除 仓库计费合同 ", notes = "删除 仓库计费合同 ", produces = MediaTypes.JSON_UTF_8)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "code", value = "合同标识", paramType = "path", dataType = "String")
    })
    @DeleteMapping(value = "/{code}")
    public Result remove(@PathVariable String code, HttpServletRequest request) {
        try {
            iContractService.remove(code);
            return Result.ok();
        } catch (Exception e) {
            log.error(StrConsts.CATCH_MESSAGE, e);
            return Result.error(e.getMessage());
        }
    }


    /**
     * 启用仓储合同
     *
     * @param codes
     * @param request
     * @return
     */
    @ApiOperation(value = "启用仓储合同", notes = "启用仓库")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "codes", value = "合同标识", required = true, paramType = "query", dataType = "List")
    })
    @PostMapping("/active")
    public Result active(@RequestParam List<String> codes, HttpServletRequest request) {
        log.info("仓储合同启用:合同标识【{}】", codes);
        if (IterUtil.isEmpty(codes)) {
            return Result.error("请选择要启用的合同");
        }

        List<String> failCodes = Lists.newArrayList();
        String failMsg = "";
        String groupCode = UserUtil.getBranchCode();
        // 线程结果集
        Map<String, Future<Boolean>> futureMap = Maps.newHashMap();
        for (String sourceCode : codes) {
            Future future = iContractService.active(sourceCode,groupCode);
            if (future == null) {
                failCodes.add(sourceCode);
            } else {
                futureMap.put(sourceCode, future);
            }
        }

        Iterator<Map.Entry<String, Future<Boolean>>> iterator = futureMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Future<Boolean>> entry = iterator.next();
            try {
                Future<Boolean> future = entry.getValue();
                while (true) {
                    if (future.isDone()){
                        Boolean status = future.get();
                        if (!status) {
                            failCodes.add(entry.getKey());
                        }
                        break;
                    }
                }
            } catch (ServiceException e) {
                log.error("仓储合同启用【{}】线程获取结果【{}】", entry.getKey(), e.getMessage());
                failMsg += "<br/><font color='red'>" + e.getMessage() + ";</font>";
                failCodes.add(entry.getKey());
            } catch (Exception e) {
                log.error("仓储合同启用【{}】线程获取结果【{}】", entry.getKey(), e.getMessage());
                failMsg += "<br/><font color='red'>" + e.getCause().getMessage() + ";</font>";
                failCodes.add(entry.getKey());
            }
        }
        return Result.ok("仓储合同启用成功" + (codes.size() - failCodes.size()) + "条；失败" + failCodes.size() + "条；" + failMsg);


    }

    /**
     * 停用仓库
     *
     * @param codes
     * @param request
     * @return
     */
    @ApiOperation(value = "停用仓储计费合同", notes = "停用仓储计费合同")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "授权token", required = true, paramType = "header", dataType = "String", defaultValue = "Bearer "),
            @ApiImplicitParam(name = "codes", value = "合同标识", required = true, paramType = "query", dataType = "List")
    })
    @PostMapping("/unactive")
    public Result unactive(@RequestParam List<String> codes, HttpServletRequest request) {

        log.info("仓储合同停用:合同标识【{}】", codes);
        if (IterUtil.isEmpty(codes)) {
            return Result.error("请选择要停用的合同");
        }
        List<String> failCodes = Lists.newArrayList();
        String failMsg = "";
        String groupCode = UserUtil.getBranchCode();
        // 线程结果集
        Map<String, Future<Boolean>> futureMap = Maps.newHashMap();
        for (String sourceCode : codes) {
            Future future = iContractService.unactive(sourceCode,groupCode);
            if (future == null) {
                failCodes.add(sourceCode);
            } else {
                futureMap.put(sourceCode, future);
            }
        }

        Iterator<Map.Entry<String, Future<Boolean>>> iterator = futureMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Future<Boolean>> entry = iterator.next();
            try {
                Boolean status = entry.getValue().get();
                if (!status) {
                    failCodes.add(entry.getKey());
                }
            } catch (ServiceException e) {
                log.error("仓储合同停用【{}】线程获取结果【{}】", entry.getKey(), e.getMessage());
                failMsg += "<br/><font color='red'>" + e.getMessage() + ";</font>";
                failCodes.add(entry.getKey());
            } catch (Exception e) {
                log.error("仓储合同停用【{}】线程获取结果【{}】", entry.getKey(), e.getMessage());
                failMsg += "<br/><font color='red'>" + e.getCause().getMessage() + ";</font>";
                failCodes.add(entry.getKey());
            }
        }
        return Result.ok("仓储合同停用成功" + (codes.size() - failCodes.size()) + "条；失败" + failCodes.size() + "条；" + failMsg);


    }


}
